


// 预编译的 SQL 语句 - uris 表
sqlite3_stmt* stmt_uris_all = NULL;
sqlite3_stmt* stmt_uris_sel = NULL;
sqlite3_stmt* stmt_uris_add = NULL;
sqlite3_stmt* stmt_uris_del = NULL;
sqlite3_stmt* stmt_uris_put = NULL;

// 添加auth表的SQL语句
sqlite3_stmt* stmt_auth_add = NULL;
sqlite3_stmt* stmt_auth_put = NULL;
sqlite3_stmt* stmt_auth_del = NULL;

// 添加authGroup表的SQL语句
sqlite3_stmt* stmt_authGroup_add = NULL;
sqlite3_stmt* stmt_authGroup_put = NULL;
sqlite3_stmt* stmt_authGroup_del = NULL;

// 添加role表的SQL语句
sqlite3_stmt* stmt_role_add = NULL;
sqlite3_stmt* stmt_role_put = NULL;
sqlite3_stmt* stmt_role_del = NULL;

// 添加user表的SQL语句
sqlite3_stmt* stmt_user_add = NULL;
sqlite3_stmt* stmt_user_put = NULL;
sqlite3_stmt* stmt_user_del = NULL;
sqlite3_stmt* stmt_user_pwd = NULL;



void Auth_CompileSQL()
{
	// 预编译 SQL 语句 - uris 表
	int iRet = sqlite3_prepare_v3(G_DB->objDB, "SELECT uris.*, auth.name, COUNT(*) OVER() AS total_count FROM uris JOIN auth ON uris.authID = auth.id ORDER BY sort ASC, id ASC LIMIT ?  OFFSET ?;", -1, SQL_PREPARE_DEFAULT, &stmt_uris_all, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init [stmt_uris_all] - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "SELECT uris.*, auth.name, COUNT(*) OVER() AS total_count FROM uris JOIN auth ON uris.authID = auth.id WHERE (uris.uri LIKE ?) OR (uris.desc LIKE ?) ORDER BY sort ASC, id ASC LIMIT ?  OFFSET ?;", -1, SQL_PREPARE_DEFAULT, &stmt_uris_sel, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init [stmt_uris_sel] - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "INSERT INTO uris (authID, uri, desc, sort, createTime) VALUES (1, ?, \"\", 0, ?);", -1, SQL_PREPARE_DEFAULT, &stmt_uris_add, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init [stmt_uris_add] - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE uris SET authID = ?, desc = ?, sort = ? WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_uris_put, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init [stmt_uris_put] - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "DELETE FROM uris WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_uris_del, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init [stmt_uris_del] - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	
	// 预编译 SQL 语句 - auth 表
	iRet = sqlite3_prepare_v3(G_DB->objDB, "INSERT INTO auth (groupID, name, desc, sort, createTime, updateTime) VALUES (?, ?, ?, ?, ?, ?);", -1, SQL_PREPARE_DEFAULT, &stmt_auth_add, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE auth SET groupID = ?, name = ?, desc = ?, sort = ?, updateTime = ? WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_auth_put, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE auth SET isDelete = 1 WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_auth_del, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	
	// 预编译 SQL 语句 - authGroup 表
	iRet = sqlite3_prepare_v3(G_DB->objDB, "INSERT INTO authGroup (name, desc, sort, createTime, updateTime) VALUES (?, ?, ?, ?, ?);", -1, SQL_PREPARE_DEFAULT, &stmt_authGroup_add, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE authGroup SET name = ?, desc = ?, sort = ?, updateTime = ? WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_authGroup_put, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE authGroup SET isDelete = 1 WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_authGroup_del, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	
	// 预编译 SQL 语句 - role 表
	iRet = sqlite3_prepare_v3(G_DB->objDB, "INSERT INTO role (name, desc, authList, createTime, updateTime, isDelete) VALUES (?, ?, ?, ?, ?, 0);", -1, SQL_PREPARE_DEFAULT, &stmt_role_add, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE role SET name = ?, desc = ?, authList = ?, updateTime = ? WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_role_put, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE role SET isDelete = 1 WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_role_del, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	
	// 预编译 SQL 语句 - user 表
	iRet = sqlite3_prepare_v3(G_DB->objDB, "INSERT INTO user (role, user, pwd, createTime, updateTime, isDelete) VALUES (?, ?, ?, ?, ?, 0);", -1, SQL_PREPARE_DEFAULT, &stmt_user_add, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE user SET role = ?, user = ?, updateTime = ? WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_user_put, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE user SET isDelete = 1 WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_user_del, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
	iRet = sqlite3_prepare_v3(G_DB->objDB, "UPDATE user SET pwd = ?, updateTime = ? WHERE id = ?;", -1, SQL_PREPARE_DEFAULT, &stmt_user_pwd, NULL);
	if ( iRet != SQLITE_OK ) {
		printf("!!! ERROR !!! Auth_Init - sqlite3_prepare_v3 error code : %d\n%s\n", iRet, sqlite3_errmsg(G_DB->objDB));
		exit(0);
	}
}



// 重新加载全局缓存
bool AuthRouteCategorize(Dict_Key* pKey, RouteInfo* pInfo, xvalue listAuth)
{
	if ( pInfo->bAuth && (pInfo->AuthID != 0) ) {
		xvalue arrAuth = xvoListGetValue(listAuth, pInfo->AuthID);
		if ( arrAuth->Type != XVO_DT_ARRAY ) {
			arrAuth = xvoCreateArray();
			xvoListSetValue(listAuth, pInfo->AuthID, arrAuth, TRUE);
		}
		xvoArrayAppendText(arrAuth, pKey->Key, pKey->KeyLen, FALSE);
	}
	return FALSE;
}
void Auth_ReloadCache()
{
	// 缓存权限组列表
	if ( G_CACHE_Auth_ComboList ) {
		xvoUnref(G_CACHE_Auth_ComboList);
	}
	XDO_Recordset rs = xdoSelect(G_DB, "SELECT id, name FROM auth ORDER BY sort ASC, id ASC;");
	G_CACHE_Auth_ComboList = xvoCreateArray();
	while ( xrsNext(rs) ) {
		xvalue tblRow = xvoCreateTable();
		int64 id = xrtStrToI64(xrsGetValue(rs, 0));
		xvoTableSetInt(tblRow, "id", 2, id);
		xvoTableSetText(tblRow, "name", 4, xrsGetValue(rs, 1), 0, FALSE);
		xvoArrayAppendValue(G_CACHE_Auth_ComboList, tblRow, TRUE);
	}
	xrsFree(rs);
	
	// 缓存权限分类列表
	if ( G_CACHE_AuthGroup_ComboList ) {
		xvoUnref(G_CACHE_AuthGroup_ComboList);
	}
	rs = xdoSelect(G_DB, "SELECT id, name FROM authGroup ORDER BY sort ASC, id ASC;");
	G_CACHE_AuthGroup_ComboList = xvoCreateArray();
	while ( xrsNext(rs) ) {
		xvalue tblRow = xvoCreateTable();
		int64 id = xrtStrToI64(xrsGetValue(rs, 0));
		xvoTableSetInt(tblRow, "id", 2, id);
		xvoTableSetText(tblRow, "name", 4, xrsGetValue(rs, 1), 0, FALSE);
		xvoArrayAppendValue(G_CACHE_AuthGroup_ComboList, tblRow, TRUE);
	}
	xrsFree(rs);
	
	// 创建角色权限表
	if ( G_CACHE_Role ) {
		xvoUnref(G_CACHE_Role);
	}
	G_CACHE_Role = xvoCreateList();
	
	// 创建权限组规则表 - 临时
	xvalue listAuth = xvoCreateList();
	xrtDictWalk(G_StaticRouteTableHTTP, (ptr)AuthRouteCategorize, listAuth);
	
	// 缓存角色列表
	if ( G_CACHE_Role_ComboList ) {
		xvoUnref(G_CACHE_Role_ComboList);
	}
	rs = xdoSelect(G_DB, "SELECT id, name, authList FROM role;");
	G_CACHE_Role_ComboList = xvoCreateArray();
	while ( xrsNext(rs) ) {
		xvalue tblRow = xvoCreateTable();
		int64 id = xrtStrToI64(xrsGetValue(rs, 0));
		xvoTableSetInt(tblRow, "id", 2, id);
		xvoTableSetText(tblRow, "name", 4, xrsGetValue(rs, 1), 0, FALSE);
		xvoArrayAppendValue(G_CACHE_Role_ComboList, tblRow, TRUE);
		// 添加角色权限表
		xvalue tblURI = xvoCreateTable();
		xvalue arrAuth = xrtParseJSON(xrsGetValue(rs, 2), 0);
		for ( int i = 1; i <= arrAuth->vArray->Count; i++ ) {
			xvalue pItem = xrtPtrArrayGet_Inline(arrAuth->vArray, i);
			xvalue arrURI = xvoListGetValue(listAuth, pItem->vInt);
			if ( arrURI->Type == XVO_DT_ARRAY ) {
				for ( int j = 1; j <= arrURI->vArray->Count; j++ ) {
					xvalue pItemURI = xrtPtrArrayGet_Inline(arrURI->vArray, j);
					xvoTableSetBool(tblURI, pItemURI->vText, pItemURI->Size, TRUE);
				}
			}
		}
		xvoUnref(arrAuth);
		xvoListSetValue(G_CACHE_Role, id, tblURI, TRUE);
	}
	xrsFree(rs);
	
	// 释放权限组规则表
	xvoUnref(listAuth);
}



// 更新 uris 表 ( 添加未收录的 URI，删除已失效的 URI )
bool AuthRouteCheckProc(Dict_Key* pKey, RouteInfo* pInfo, ptr param)
{
	if ( pInfo->bAuth && (pInfo->AuthID == 0) ) {
		printf("            new uris table item : %.*s\n", pKey->KeyLen, pKey->Key);
		sqlite3_bind_text(stmt_uris_add, 1, pKey->Key, pKey->KeyLen, SQLITE_STATIC);
		sqlite3_bind_int64(stmt_uris_add, 2, xrtNow());
		sqlite3_step(stmt_uris_add);
		sqlite3_reset(stmt_uris_add);
		pInfo->AuthID = 1;
	}
	return FALSE;
}
void Auth_UpdateURIS()
{
	// 删除数据库中存在，但路由表中不存在的记录
	XDO_Recordset rs = xdoSelect(G_DB, "SELECT id, authID, uri FROM uris;");
	while ( xrsNext(rs) ) {
		int64 id = xrtStrToI64(xrsGetValue(rs, 0));
		int64 authID = xrtStrToI64(xrsGetValue(rs, 1));
		str uri = xrsGetValue(rs, 2);
		size_t iSize = strlen(uri);
		RouteInfo* pInfo = xrtDictGet(G_StaticRouteTableHTTP, uri, iSize);
		if ( pInfo ) {
			pInfo->AuthID = authID;
		} else {
			printf("            remove uris table item : %.*s (%d)\n", iSize, uri, id);
			sqlite3_bind_int64(stmt_uris_del, 1, id);
			sqlite3_step(stmt_uris_del);
			sqlite3_reset(stmt_uris_del);
		}
	}
	xrsFree(rs);
	// 遍历路由表，将数据库中不存在的记录添加进去
	xrtDictWalk(G_StaticRouteTableHTTP, (ptr)AuthRouteCheckProc, NULL);
}



// 权限模块初始化
void Auth_Init()
{
	// 预编译 SQL 语句
	Auth_CompileSQL();
	
	// 更新 uris 表 ( 添加未收录的 URI，删除已失效的 URI )
	Auth_UpdateURIS();
	
	// 重新加载全局缓存
	Auth_ReloadCache();
}



// 卸载权限模块
void Auth_Unit()
{
	sqlite3_finalize(stmt_uris_all);
	sqlite3_finalize(stmt_uris_sel);
	sqlite3_finalize(stmt_uris_add);
	sqlite3_finalize(stmt_uris_del);
	sqlite3_finalize(stmt_uris_put);
	sqlite3_finalize(stmt_auth_add);
	sqlite3_finalize(stmt_auth_put);
	sqlite3_finalize(stmt_auth_del);
	sqlite3_finalize(stmt_authGroup_add);
	sqlite3_finalize(stmt_authGroup_put);
	sqlite3_finalize(stmt_authGroup_del);
	sqlite3_finalize(stmt_role_add);
	sqlite3_finalize(stmt_role_put);
	sqlite3_finalize(stmt_role_del);
	sqlite3_finalize(stmt_user_add);
	sqlite3_finalize(stmt_user_put);
	sqlite3_finalize(stmt_user_del);
	sqlite3_finalize(stmt_user_pwd);
	
	// 释放全局缓存表
	xvoUnref(G_CACHE_Role);
	xvoUnref(G_CACHE_Auth_ComboList);
	xvoUnref(G_CACHE_AuthGroup_ComboList);
	xvoUnref(G_CACHE_Role_ComboList);
}


